package com.usooft.metaTalent.admin.base;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.usooft.framework.core.utils.MapBuilder;
import com.usooft.framework.web.session.LoginSession;
import com.usooft.metaTalent.core.system.entity.Employee;
import com.usooft.metaTalent.core.system.entity.EmployeeWxOpenUser;
import com.usooft.metaTalent.core.system.service.EmployeeService;
import com.usooft.metaTalent.core.system.service.EmployeeWxOpenUserService;
import com.usooft.metaTalent.core.wx.entity.WxOpenUser;
import com.usooft.metaTalent.core.wx.service.WxOpenUserService;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Optional;

import static com.usooft.framework.core.utils.Checks.check;

@RestController
@RequestMapping("/login")
@RequiredArgsConstructor
public class LoginController {

    /**
     * 短信验证场景：管理端短信验证码
     */
    private static final String SCENE_PARENT_LOGIN_SMS = "admin.login.sms";

    private final EmployeeService employeeService;
    private final LoginSession loginSession;
    private final EmployeeWxOpenUserService employeeWxOpenUserService;
    private final String JWT_SECRET = "ln4u9I9kZiXqvN82MkVXw4MiX2AUf56O";
    @Autowired(required = false)
    private WxMpService wxMpService;
    @Autowired(required = false)
    private WxOpenUserService wxOpenUserService;


    private void bindEmployeeAndWxOpenUser(Employee employee, String bindingToken) {
        DecodedJWT decodedJWT;
        try {
            decodedJWT = JWT.require(Algorithm.HMAC256(JWT_SECRET))
                    .withIssuer("wx-open-login")
                    .build()
                    .verify(bindingToken);
        } catch (JWTVerificationException e) {
            throw new IllegalArgumentException("登录已超时，请刷新重试 ~");
        }
        Long wxOpenUserId = decodedJWT.getClaim("wxOpenUserId").asLong();
        WxOpenUser wxOpenUser = wxOpenUserService.get(wxOpenUserId);

        employeeWxOpenUserService.create(employee, wxOpenUser);
    }


    @PostMapping("/password")
    public ResponseEntity<?> password(String phoneNumber,
                                      String password,
                                      String bindingToken) {
        Optional<? extends Employee> userOptional = employeeService.findByPhoneNumber(phoneNumber);
        check(userOptional.isPresent(), "手机号或密码不正确");

        Employee employee = userOptional.get();
        check(!employee.getLocked(), "账户已被锁定");
        check(employeeService.matchPassword(employee, password), "手机号或密码不正确");

        if (bindingToken != null) {
            bindEmployeeAndWxOpenUser(employee, bindingToken);
        }
        loginSession.set(employee.getId());

        return ResponseEntity.ok().build();
    }

    @PostMapping("/wx-open")
    public ResponseEntity<?> scan(String code) throws WxErrorException {
        WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);

        String unionId = accessToken.getUnionId();
        WxOpenUser wxOpenUser = wxOpenUserService.findByUnionId(unionId)
                .orElseGet(() -> wxOpenUserService.create(
                        unionId,
                        accessToken.getOpenId()
                ));

        Optional<EmployeeWxOpenUser> optionalEmployeeWxOpenUser = employeeWxOpenUserService.findByWxOpenUser(wxOpenUser);
        if (optionalEmployeeWxOpenUser.isEmpty()) {
            // 未绑定员工，需进行绑定
            String token = JWT.create()
                    .withIssuer("wx-open-login")
                    .withExpiresAt(Instant.now().plus(10, ChronoUnit.MINUTES))
                    .withClaim("wxOpenUserId", wxOpenUser.getId())
                    .sign(Algorithm.HMAC256(JWT_SECRET));
            return ResponseEntity.ok(MapBuilder.builder()
                    .put("binding", false)
                    .put("token", token)
                    .build());
        }

        // 已绑定员工，直接登录
        EmployeeWxOpenUser employeeWxOpenUser = optionalEmployeeWxOpenUser.get();
        loginSession.set(employeeWxOpenUser.getEmployeeId());

        return ResponseEntity.ok(MapBuilder.builder()
                .put("binding", true)
                .build());
    }
}
